package com.dhj.yygh.controller.api;

import com.dhj.yygh.common.exception.YyghException;
import com.dhj.yygh.common.helper.HttpRequestHelper;
import com.dhj.yygh.common.result.MyResult;
import com.dhj.yygh.common.result.ResultCodeEnum;
import com.dhj.yygh.common.utils.MD5;
import com.dhj.yygh.model.hosp.Department;
import com.dhj.yygh.model.hosp.Hospital;
import com.dhj.yygh.model.hosp.Schedule;
import com.dhj.yygh.mongo_operation.DepartmentTemplate;
import com.dhj.yygh.service.DepartmentService;
import com.dhj.yygh.service.HospitalService;
import com.dhj.yygh.service.HospitalSetService;
import com.dhj.yygh.service.ScheduleService;
import com.dhj.yygh.vo.hosp.DepartmentQueryVo;
import com.dhj.yygh.vo.hosp.ScheduleQueryVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.tomcat.util.security.MD5Encoder;
import org.omg.PortableInterceptor.INACTIVE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/*
该 com.dhj.yygh.controller 需要对外暴露，因此单独放到 api 包下，以便区分
 */
@Api(tags = "医院管理 api 接口")
@RestController
@RequestMapping("/api/hosp")
public class ApiController {

    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private HospitalSetService hospitalSetService;

    @Autowired
    private DepartmentService departmentService;

    @Autowired
    private ScheduleService scheduleService;

    /*
    医院调用平台接口的流程分析:
    每个医院在平台开通后，会得到自己医院的设置信息(包含 signKey | hoscode | 平台提供给医院的调用接口等)
    医院可以将该设置信息保存到自己的医院系统中
    医院可以修改这个设置信息，平台需要对医院更新设置后的信息进行更新，否则医院无法调用平台这边的接口
    其每次需要进行上传 | 修改医院信息等接口的调用时，平台会在自己的 hosp_set 数据库中查询
    是否有该医院的 signKey 签名信息，若有，则可以调用平台的接口，通过上述操作，保证只有在平台开通的医院
    能够调用相关接口，防止其他人恶意的接口调用发布虚假信息等，保证数据的安全性

    特别注意，医院与平台使用的 MD5 加密方式一定要一致
     */
    @ApiOperation("上传医院接口")
    @PostMapping("/saveHospital")
    public MyResult saveHospital(HttpServletRequest req) {

        // 获取医院传递过来的数据
        Map<String, String[]> parameterMap = req.getParameterMap();

        // 转换以下，方便操作
        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        // 获取医院系统传递过来的签名,签名为 MD5 加密
        String hospSignKey = (String) stringObjectMap.get("sign");

        /*
         根据 hoscode 查询数据库中对应医院的签名

         服务端不要根据传过来的 id 查询医院信息
         例如，医院在自己的数据库中按照 id 为 1 查询出的医院信息 Hosptial 传递过来
         若服务端也根据该 id 查询自己数据库中的医院设置 HospitalSet 数据
         则不敢保证数据库中 id 为 1 的就一定是该医院的信息，因为服务端大概率存储了多家医院的信息
         而 hoscode 则是唯一的，可以区分不同的医院
         */
        String hoscode = (String) stringObjectMap.get("hoscode");

        // 获取数据库中的 signKey
        String hospitalSetSignKey = hospitalSetService.getHospitalSetSignKey(hoscode);

        // 通过 MD5 加密
        String hospSetSignKey = MD5.encrypt(hospitalSetSignKey);

        // 若签名一致，则进行添加或更新操作
        if (hospSetSignKey.equals(hospSignKey)) {

            /*
             解决医院 logo 的 Base64 编码问题
             图片的 base64 编码就是可以将一张图片数据编码成一串字符串，使用该字符串代替图像地址 url
             在前端页面中常见的 base64 图片的引入方式
             <img src="...">
             */

            String logoData = (String) stringObjectMap.get("logoData");
            System.out.println(logoData);

            /*
            图片转换为base64字符串时，该字符串中包含大量的加号“+”，服务器在解析数据时会把加号当成连接符，转换为空格，
            因此我们要做一下特殊处理，将字符串中的 " " 替换为 "+"
             */
            logoData = logoData.replaceAll(" ", "+");

            System.out.println(logoData);
            // 修正后的 base64 重新放入集合中
            stringObjectMap.put("logoData", logoData);

            hospitalService.save(stringObjectMap);
            return MyResult.ok();
        }
        throw new YyghException((ResultCodeEnum.SIGN_ERROR));
    }

    @ApiOperation("查询医院接口")
    @PostMapping("/hospital/show")
    public MyResult showHospital(HttpServletRequest req) {

        Map<String, String[]> parameterMap = req.getParameterMap();

        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        // 验证签名
        if (hospitalService.checkSignKey(stringObjectMap)) {
            String hoscode = (String) stringObjectMap.get("hoscode");

            // 根据医院 hoscode 查询医院信息
            Hospital hospitalByHoscode = hospitalService.getHospitalByHoscode(hoscode);
            return MyResult.ok(hospitalByHoscode);
        }
        throw new YyghException("签名错误!", 201);
    }

    @ApiOperation("科室信息上传接口")
    @PostMapping("/saveDepartment")
    public MyResult saveDepartment(HttpServletRequest req) {
        Map<String, String[]> parameterMap = req.getParameterMap();
        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        // 签名验证
        if (hospitalService.checkSignKey(stringObjectMap)) {
            departmentService.saveDepartment(stringObjectMap);
            return MyResult.ok();
        }
        throw new YyghException(ResultCodeEnum.SIGN_ERROR);
    }

    @ApiOperation("科室信息分页条件查询接口")
    @PostMapping("/department/list")
    public MyResult<Page<Department>> departmentPage(HttpServletRequest req) {
        Map<String, String[]> parameterMap = req.getParameterMap();
        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        // 签名验证
        if (!hospitalService.checkSignKey(stringObjectMap)) {
            return MyResult.fail();
        }

        String hoscode = (String) stringObjectMap.get("hoscode");

        Integer page = StringUtils.isEmpty(stringObjectMap.get("page")) ? 1 :
                Integer.parseInt((String) stringObjectMap.get("page"));

        Integer limit = StringUtils.isEmpty(stringObjectMap.get("limit")) ? 1 :
                Integer.parseInt((String) stringObjectMap.get("limit"));


        DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();

        // 设置查询条件对象中的医院编号
        departmentQueryVo.setHoscode(hoscode);

        Page<Department> deparmentPage = departmentService
                // MongoRepository 中，页数从 0 开始
                .getDeparmentPage(page - 1, limit, departmentQueryVo);

        return MyResult.ok(deparmentPage);
    }

    @ApiOperation("科室删除接口")
    @PostMapping("/department/remove")
    public MyResult removeDeparment(HttpServletRequest req) {
        Map<String, String[]> parameterMap = req.getParameterMap();

        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        // 签名验证
        if (!hospitalService.checkSignKey(stringObjectMap)) {
            return MyResult.fail();
        }

        String depcode = (String) stringObjectMap.get("depcode");
        String hoscode = (String) stringObjectMap.get("hoscode");

        Long removeCount = departmentService.removeDepartmentByDepcodeAndHoscode(hoscode, depcode);

        return removeCount > 0L ? MyResult.ok(removeCount) : MyResult.fail();
    }

    @ApiOperation("上传排班接口")
    @PostMapping("/saveSchedule")
    public MyResult saveSchedule(HttpServletRequest req) {

        Map<String, String[]> parameterMap = req.getParameterMap();
        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        if (!hospitalService.checkSignKey(stringObjectMap)) {
            return MyResult.fail("签名校验失败!");
        }
        scheduleService.saveSchedule(stringObjectMap);

        return MyResult.ok();
    }

    @ApiOperation("排班分页查询")
    @PostMapping("/schedule/list")
    public MyResult<Page<Schedule>> getSchedulePage(HttpServletRequest req) {

        Map<String, String[]> parameterMap = req.getParameterMap();

        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        if (!hospitalService.checkSignKey(stringObjectMap)) {
            return MyResult.fail();
        }

        Integer page = StringUtils.isEmpty((String) stringObjectMap.get("page")) ? 1 :
                Integer.parseInt((String) stringObjectMap.get("page"));

        Integer limit = StringUtils.isEmpty((String) stringObjectMap.get("limit")) ? 1 :
                Integer.parseInt((String) stringObjectMap.get("limit"));

        ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
        scheduleQueryVo.setHoscode((String) stringObjectMap.get("hoscode"));

        Page<Schedule> schedulePage = scheduleService.getPageByHoscode(page, limit, scheduleQueryVo);

        return MyResult.ok(schedulePage);
    }


    @ApiOperation("删除排班信息")
    @PostMapping("/schedule/remove")
    public MyResult removeSchedule(HttpServletRequest req) {

        Map<String, String[]> parameterMap = req.getParameterMap();

        Map<String, Object> stringObjectMap = HttpRequestHelper.switchMap(parameterMap);

        // 签名校验
        if (!hospitalService.checkSignKey(stringObjectMap)) {
            return MyResult.fail("签名校验失败!");
        }

        String hoscode = (String) stringObjectMap.get("hoscode");
        String hosShcedule = (String) stringObjectMap.get("hosSchedule");

        Long removeCount = scheduleService.removeByHoscodeAndHosSchedule(hoscode, hosShcedule);

        return removeCount > 0L ? MyResult.ok(removeCount) : MyResult.fail(0L);
    }
}
